{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d760e6e6",
   "metadata": {},
   "source": [
    "# Relativistic Value at Risk Portfolio Optimization\n",
    "\n",
    "In this notebook we show how to use the power cone and its application in portfolio optimization.\n",
    "\n",
    "## 1. Relativistic Value at Risk (RLVaR) Optimization\n",
    "\n",
    "__[Cajas (2023)](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3792520)__ proposed a generalization of Entropic Value at Risk (EVaR) __[Ahmadi-Javid (2012)](https://link.springer.com/article/10.1007/s10957-011-9968-2?r=1&l=ri&fst=0&error=cookies_not_supported&code=ccfb8a5e-692b-43d1-b76e-ae596c7f0bed)__ based on Kaniadakis entropy __[Kaniadakis (2001)](https://www.sciencedirect.com/science/article/pii/S0378437101001844)__. We can pose the minimization of Relativistic Value at Risk as the following convex programming problem: \n",
    "\n",
    "$$\n",
    "\\begin{equation}\n",
    "\\begin{aligned}\n",
    "& \\underset{x, z, t, \\psi, \\theta,  \\varepsilon, \\omega}{\\text{min}} & &   t + z \\ln_{\\kappa} \\left ( \\frac{1}{\\alpha T} \\right ) + \\sum^T_{j=1} \\left ( \\psi_{j} + \\theta_{j}  \\right ) \\\\\n",
    "& \\text{s.t.} & & -r_{j} x  - t + \\varepsilon_{j} + \\omega_{j} \\leq 0  \\; ; \\;  \\forall j =1, \\ldots ,T \\\\\n",
    "& & & z \\geq 0 \\\\\n",
    "& & & \\left ( z \\left ( \\frac{1+\\kappa}{2\\kappa} \\right ), \\psi_{j} \\left ( \\frac{1+\\kappa}{\\kappa} \\right ), \\varepsilon_{j} \\right) \\in \\mathcal{P}_3^{1/(1+\\kappa),\\, \\kappa/(1+\\kappa)} \\\\ \n",
    "& & & \\left ( \\omega_{j}\\left ( \\frac{1}{1-\\kappa} \\right ), \\theta_{j}\\left ( \\frac{1}{\\kappa} \\right),  -z \\left ( \\frac{1}{2\\kappa} \\right ) \\right ) \\in \\mathcal{P}_3^{1-\\kappa,\\, \\kappa} \\\\\n",
    "& & &  \\sum_{i=1}^{n} x_i = 1 \\\\\n",
    "& & &  x_i \\geq 0 \\; ; \\; \\forall \\; i =1, \\ldots, n \\\\\n",
    "\\end{aligned}\n",
    "\\end{equation}\n",
    "\n",
    "$$\n",
    "\n",
    "Where $t$, $z$ $\\psi$, $\\theta$, $\\epsilon$ and $\\omega$ are auxiliary variables, $x$ are the weights of portfolio assets of size $n \\times 1$, $\\mathcal{P}^{\\alpha, 1-\\alpha}$ is a power cone, $r$ is the matrix of observed returns and $\\kappa$ is the deformation parameter of Kaniadakis logarithm."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2a19278a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[*********************100%***********************]  14 of 14 completed\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>BAX</th>\n",
       "      <th>BMY</th>\n",
       "      <th>CMCSA</th>\n",
       "      <th>CNP</th>\n",
       "      <th>CPB</th>\n",
       "      <th>GE</th>\n",
       "      <th>GOOG</th>\n",
       "      <th>MO</th>\n",
       "      <th>MSFT</th>\n",
       "      <th>NI</th>\n",
       "      <th>SEE</th>\n",
       "      <th>T</th>\n",
       "      <th>TGT</th>\n",
       "      <th>VZ</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2016-01-05</th>\n",
       "      <td>0.4035%</td>\n",
       "      <td>1.9693%</td>\n",
       "      <td>0.0180%</td>\n",
       "      <td>0.9305%</td>\n",
       "      <td>0.3678%</td>\n",
       "      <td>0.0977%</td>\n",
       "      <td>0.0998%</td>\n",
       "      <td>2.0213%</td>\n",
       "      <td>0.4562%</td>\n",
       "      <td>1.5881%</td>\n",
       "      <td>0.9759%</td>\n",
       "      <td>0.6987%</td>\n",
       "      <td>1.7539%</td>\n",
       "      <td>1.3734%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2016-01-06</th>\n",
       "      <td>0.2412%</td>\n",
       "      <td>-1.7557%</td>\n",
       "      <td>-0.7727%</td>\n",
       "      <td>-1.2473%</td>\n",
       "      <td>-0.1736%</td>\n",
       "      <td>-1.5940%</td>\n",
       "      <td>0.1400%</td>\n",
       "      <td>1.0589%</td>\n",
       "      <td>-1.8165%</td>\n",
       "      <td>0.5547%</td>\n",
       "      <td>-1.5647%</td>\n",
       "      <td>0.3108%</td>\n",
       "      <td>-1.0155%</td>\n",
       "      <td>-0.9034%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2016-01-07</th>\n",
       "      <td>-1.6573%</td>\n",
       "      <td>-2.7699%</td>\n",
       "      <td>-1.1047%</td>\n",
       "      <td>-1.9770%</td>\n",
       "      <td>-1.2206%</td>\n",
       "      <td>-4.2314%</td>\n",
       "      <td>-2.3170%</td>\n",
       "      <td>-1.7407%</td>\n",
       "      <td>-3.4783%</td>\n",
       "      <td>-2.2067%</td>\n",
       "      <td>-3.1557%</td>\n",
       "      <td>-1.6148%</td>\n",
       "      <td>-0.2700%</td>\n",
       "      <td>-0.5492%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2016-01-08</th>\n",
       "      <td>-1.6037%</td>\n",
       "      <td>-2.5425%</td>\n",
       "      <td>0.1099%</td>\n",
       "      <td>-0.2241%</td>\n",
       "      <td>0.5706%</td>\n",
       "      <td>-1.7949%</td>\n",
       "      <td>-1.6410%</td>\n",
       "      <td>0.1720%</td>\n",
       "      <td>0.3067%</td>\n",
       "      <td>-0.1538%</td>\n",
       "      <td>-0.1448%</td>\n",
       "      <td>0.0896%</td>\n",
       "      <td>-3.3839%</td>\n",
       "      <td>-0.9719%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2016-01-11</th>\n",
       "      <td>-1.6851%</td>\n",
       "      <td>-1.0215%</td>\n",
       "      <td>0.0914%</td>\n",
       "      <td>-1.1791%</td>\n",
       "      <td>0.5674%</td>\n",
       "      <td>0.4569%</td>\n",
       "      <td>0.2183%</td>\n",
       "      <td>2.0947%</td>\n",
       "      <td>-0.0573%</td>\n",
       "      <td>1.6436%</td>\n",
       "      <td>-0.1450%</td>\n",
       "      <td>1.2224%</td>\n",
       "      <td>1.4570%</td>\n",
       "      <td>0.5799%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                BAX      BMY    CMCSA      CNP      CPB       GE     GOOG  \\\n",
       "Date                                                                        \n",
       "2016-01-05  0.4035%  1.9693%  0.0180%  0.9305%  0.3678%  0.0977%  0.0998%   \n",
       "2016-01-06  0.2412% -1.7557% -0.7727% -1.2473% -0.1736% -1.5940%  0.1400%   \n",
       "2016-01-07 -1.6573% -2.7699% -1.1047% -1.9770% -1.2206% -4.2314% -2.3170%   \n",
       "2016-01-08 -1.6037% -2.5425%  0.1099% -0.2241%  0.5706% -1.7949% -1.6410%   \n",
       "2016-01-11 -1.6851% -1.0215%  0.0914% -1.1791%  0.5674%  0.4569%  0.2183%   \n",
       "\n",
       "                 MO     MSFT       NI      SEE        T      TGT       VZ  \n",
       "Date                                                                       \n",
       "2016-01-05  2.0213%  0.4562%  1.5881%  0.9759%  0.6987%  1.7539%  1.3734%  \n",
       "2016-01-06  1.0589% -1.8165%  0.5547% -1.5647%  0.3108% -1.0155% -0.9034%  \n",
       "2016-01-07 -1.7407% -3.4783% -2.2067% -3.1557% -1.6148% -0.2700% -0.5492%  \n",
       "2016-01-08  0.1720%  0.3067% -0.1538% -0.1448%  0.0896% -3.3839% -0.9719%  \n",
       "2016-01-11  2.0947% -0.0573%  1.6436% -0.1450%  1.2224%  1.4570%  0.5799%  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "####################################\n",
    "# Downloading Data\n",
    "####################################\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import yfinance as yf\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings(\"ignore\")\n",
    "\n",
    "yf.pdr_override()\n",
    "pd.options.display.float_format = '{:.4%}'.format\n",
    "\n",
    "# Date range\n",
    "start = '2016-01-01'\n",
    "end = '2019-12-30'\n",
    "\n",
    "# Tickers of assets\n",
    "assets = ['TGT', 'CMCSA', 'CPB', 'MO', 'T', 'BAX', 'BMY',\n",
    "          'MSFT', 'SEE', 'VZ', 'CNP', 'NI', 'GE', 'GOOG']\n",
    "assets.sort()\n",
    "\n",
    "# Downloading data\n",
    "data = yf.download(assets, start = start, end = end)\n",
    "data = data.loc[:,('Adj Close', slice(None))]\n",
    "data.columns = assets\n",
    "\n",
    "# Calculating returns\n",
    "Y = data[assets].pct_change().dropna()\n",
    "\n",
    "display(Y.head())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "94d0f382",
   "metadata": {},
   "outputs": [],
   "source": [
    "####################################\n",
    "# Auxiliary functions\n",
    "####################################\n",
    "\n",
    "# Function that calculates the Kaniadakis logarithm\n",
    "def ln_k(x, kappa=0.3):\n",
    "    return (x**kappa - x**(-kappa))/(2*kappa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "583f7d9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Weights</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>BAX</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>BMY</th>\n",
       "      <td>9.9856%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CMCSA</th>\n",
       "      <td>6.9171%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CNP</th>\n",
       "      <td>12.0874%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CPB</th>\n",
       "      <td>15.2284%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>GE</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>GOOG</th>\n",
       "      <td>5.4628%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MO</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>MSFT</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>NI</th>\n",
       "      <td>17.1999%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>SEE</th>\n",
       "      <td>14.5753%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>T</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TGT</th>\n",
       "      <td>18.5435%</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>VZ</th>\n",
       "      <td>0.0000%</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "       Weights\n",
       "BAX    0.0000%\n",
       "BMY    9.9856%\n",
       "CMCSA  6.9171%\n",
       "CNP   12.0874%\n",
       "CPB   15.2284%\n",
       "GE     0.0000%\n",
       "GOOG   5.4628%\n",
       "MO     0.0000%\n",
       "MSFT   0.0000%\n",
       "NI    17.1999%\n",
       "SEE   14.5753%\n",
       "T      0.0000%\n",
       "TGT   18.5435%\n",
       "VZ     0.0000%"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "####################################\n",
    "# Finding the Min EVaR Portfolio\n",
    "####################################\n",
    "\n",
    "import cvxpy as cp\n",
    "\n",
    "# Defining initial parameters\n",
    "returns = Y.to_numpy()\n",
    "T, n = Y.shape\n",
    "alpha = 0.05\n",
    "kappa = 0.3\n",
    "\n",
    "# Defining initial variables\n",
    "w = cp.Variable((n, 1))\n",
    "X = returns @ w\n",
    "t = cp.Variable((1, 1))\n",
    "z = cp.Variable((1, 1), nonneg=True)\n",
    "omega = cp.Variable((T, 1))\n",
    "psi = cp.Variable((T, 1))\n",
    "theta = cp.Variable((T, 1))\n",
    "epsilon = cp.Variable((T, 1))\n",
    "onesvec = np.ones((T, 1))\n",
    "\n",
    "constraints = [\n",
    "    cp.PowCone3D(\n",
    "        z * (1 + kappa) / (2 * kappa) * onesvec,\n",
    "        psi * (1 + kappa) / kappa,\n",
    "        epsilon,\n",
    "        1 / (1 + kappa),\n",
    "    ),\n",
    "    cp.PowCone3D(\n",
    "        omega / (1 - kappa),\n",
    "        theta / kappa,\n",
    "        -z / (2 * kappa) * onesvec,\n",
    "        (1 - kappa),\n",
    "    ),\n",
    "    -X * 1000 - t * 1000 + epsilon * 1000 + omega * 1000 <= 0,\n",
    "    cp.sum(w) == 1,\n",
    "    w >= 0\n",
    "]\n",
    "\n",
    "# Defining risk objective\n",
    "risk = t + z * ln_k(1 / (alpha * T), kappa) + cp.sum(psi + theta)\n",
    "objective = cp.Minimize(risk)\n",
    "\n",
    "# Solving problem\n",
    "prob = cp.Problem(objective, constraints)\n",
    "prob.solve()\n",
    "\n",
    "# Showing Optimal Weights\n",
    "weights = pd.DataFrame(w.value, index=assets, columns=['Weights'])\n",
    "display(weights)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "de8cc7f7",
   "metadata": {},
   "source": [
    "This portfolio optimization model is available in the CVXPY based library __[Riskfolio-Lib](https://github.com/dcajasn/Riskfolio-Lib)__.\n",
    "\n",
    "Finally, I hope you liked this example."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
